;;
;; @file     le-emacs-eshell.el
;; @created  2011/10/23
;; @author   Gan Xiangle
;; @brief    Configure eshell in emacs.The 'shell' is differ to
;;           eshell which is written in elisp, the 'shell' invoke
;;           the native shell, on Windows, it's the ENV variable
;;           'ComSpec'(value: C:\WINDOWS\system32\cmd.exe )
;;          
;; @usage   just load this file.



;;don't echo
(defun my-comint-init ()
  (setq comint-process-echoes t))
(add-hook 'comint-mode-hook 'my-comint-init)

;; * tab
(defun user-tab ()
  (interactive)
  (let ((input (eshell-get-old-input)))
    (if (string-equal input "")
        (insert-string "cd ")
      (progn
        (cond
         ((string-equal input "cd  ")
          (delete-backward-char 1)
          (insert-string "-0"))
         ((string-match "^cd\\ -[0-9]+$" input)
          (let ((len (length input)))
            (delete-backward-char (- len 4))
            (insert-string (1+ (read(substring input 4 len))))))
         (t
          (pcomplete))
         )))))

;; * ret
(defun user-ret ()
  (interactive)
  (let ((input (eshell-get-old-input)))
    (if (string-equal input "")
        (progn
          (insert-string "ls")
          (eshell-send-input))
      (progn
        (cond
         ((string-match "^cd\\ \\.\\{2,\\}$" input)
          (let ((len (- (length input) 5))
                (dots (lambda (n d)(if (<= n 0) nil (concat (funcall dots (1- n) d) d)))))
            (eshell-bol)(kill-line)
            (insert-string (concat "cd .." (funcall dots len "/..")))
            (eshell-send-input)))
         ((string-match "^\\.\\{2,\\}$" input)
          (let ((len (- (length input) 2))(p ".."))
            (while (> len 0)
              (setq len (1- len))(setq p (concat p "/..")))
            (eshell-bol)(kill-line)
            (insert-string p)
            (eshell-send-input)))
         (t
          (eshell-send-input))))
      )))

;; * spc
(defun user-spc ()
  (interactive)
  (let ((input (eshell-get-old-input)))
    (if (string-equal input "")
        (insert-string "!-1")
      (progn
        (cond
         ((string-match "^!-[0-9]+$" input)
          (let ((len (length input)))
            (delete-backward-char (- len 2))
            (insert-string (1+ (read(substring input 2 len))))))
         (t
          (self-insert-command 1))
         )))))

(provide 'eshell-user-key)


(add-hook 'eshell-mode-hook (lambda()
			      (outline-minor-mode 1)			      
			      (setq outline-regexp "^[^#$\n]* [#>]+ "
				    scroll-margin 0
				    eshell-scroll-to-bottom-on-output t
				    eshell-scroll-show-maximum-output t)
			      (add-to-list 'eshell-output-filter-functions 
					   'eshell-postoutput-scroll-to-bottom)
			      (def-key-s eshell-mode-map 
				"<up>"     'eshell-previous-matching-input-from-input
				"<down>"   'eshell-next-matching-input-from-input
				"<tab>"    'user-tab
				"<return>" 'user-ret
				"SPC"      'user-spc
				)
			      ))

(setq eshell-save-history-on-exit t 
      eshell-history-size 512 
      eshell-hist-ignoredups t 
      eshell-cmpl-ignore-case t 
      eshell-cp-interactive-query t 
      eshell-ln-interactive-query t 
      eshell-mv-interactive-query t 
      eshell-rm-interactive-query t 
      eshell-mv-overwrite-files nil 
      eshell-highlight-prompt t
      ;; 提示符设置，下面两项必须对应起来，
      ;; 否则会报 read-only，并且不能补全什么的
      eshell-prompt-regexp      "^[^#$\n]* [#>]+ "
      eshell-prompt-function    (lambda nil
                                  (concat
                                   (abbreviate-file-name
                                    (eshell/pwd))
                                   (if
                                       (=
                                        (user-uid)
                                        0)
                                       " # " " >>> ")))
      )

;;show how much time a command used
(add-hook 'eshell-load-hook
          (lambda()(setq last-command-start-time (time-to-seconds))))
(add-hook 'eshell-pre-command-hook
          (lambda()(setq last-command-start-time (time-to-seconds))))
(add-hook 'eshell-before-prompt-hook
          (lambda()
	    (message "spend %g seconds"
		     (- (time-to-seconds) last-command-start-time))))

;;frequen used commands
(defalias 'ff 'find-file)
(defalias 'aa (lambda()(find-file eshell-aliases-file)))
(defalias 'rr (lambda()(find-file (expand-file-name "qref.org" sand-box))))
(defalias 'ss  'shell-command-to-string)

;; ;;config of auto complete
;; (defvar ac-source-eshell-pcomplete
;;   '((candidates . (pcomplete-completions))))
;; (defun ac-complete-eshell-pcomplete ()
;;   (interactive)
;;   (auto-complete '(ac-source-eshell-pcomplete)))
;; ;; 自动开启 auto-complete-mode
;; (global-auto-complete-mode 1)
;; (add-to-list 'ac-modes 'eshell-mode)
;; (setq ac-sources '(ac-source-eshell-pcomplete
;;                     ac-source-files-in-current-dir
;;                    ;; ac-source-filename
;;                    ;; ac-source-abbrev
;;                    ;; ac-source-words-in-buffer
;;                    ;; ac-source-imenu
;; 		   ))

























